package com.lzz.bottomencapsulation.view.activity.needone;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;

import com.lzz.bottomencapsulation.utils.LUtils;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/***
 * pz格式说明

 pz为zip压缩文件
 zip内压缩png序列文件及一个config文件

 config文件定义pz动画帧数、播放次数及每帧的停留时间
 pz帧顺序按照压缩进pz文件的顺序排列
 如压缩顺序为：009.png  008.png  003.png 007.png
 则第1帧为009.png 第2帧为008.png 第3帧为003.png 第4帧为007.png
 （不按照文件名顺序）


 config文件定义
 起始字节  字节数 说明
 0   4  帧数
 4   4  播放次数
 8   4  第1帧停留时间
 12   4  第2帧停留时间
 ...
 ?   4  第N帧停留时间

 每帧停留时间按照顺序排列**/
public class AnimationsContainer {
    public int playCount;//播放次数  ==0时：无限循环播放
    public int framenum;//播放帧数
    private ArrayList<ImageByteConfig> images;//压缩文件读取的图片字符流和每一帧停留时间的集合
    // 单例
    private static AnimationsContainer mInstance;

    public AnimationsContainer() {
    }

    /**
     * 获取单例
     *
     * @param zipPath 压缩文件路径
     * @return
     */
    public static AnimationsContainer getInstance(String zipPath) {
        if (mInstance == null) {
            mInstance = new AnimationsContainer();
        }
        mInstance.setResId(mInstance.getBitmapByteArrayOutputStream(zipPath));
        return mInstance;
    }

    /***
     * 获取指定路径下压缩文件的bitmap字符流以及配置参数
     * @param zipPath 获取压缩文件的路径
     * @return
     */
    private ArrayList<ImageByteConfig> getBitmapByteArrayOutputStream(String zipPath) {
        ArrayList<ByteArrayOutputStream> byteArrayOutputStreams = new ArrayList<>();//图片读取的字节
        ArrayList<ImageByteConfig> imageByteConfigs = new ArrayList<>();//图片及配置暂存集合
        ZipFile zf = null;//压缩文件对象
        ByteBuffer config = null;//配置文件读取的字符
        int delay_time;//每一帧显示的时长
        int len;
        try {
            zf = new ZipFile(zipPath);
            InputStream in = new BufferedInputStream(new FileInputStream(zipPath));
            ZipInputStream zin = new ZipInputStream(in);
            ZipEntry ze;

            while ((ze = zin.getNextEntry()) != null) {
                if (ze.isDirectory()) {
                    //Do nothing
                } else if (ze.getName().equals("config")) {
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    while ((len = zin.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                    }
                    config = ByteBuffer.wrap(out.toByteArray());
                    config.order(ByteOrder.LITTLE_ENDIAN);
                } else {

//                判断文件是否是png
                    String zePath = ze.getName();//文件的路径
                    String zeType = "";//文件类型
                    int zeTypeNum = zePath.lastIndexOf('.');//找到图片名称的位置
                    if (zeTypeNum != -1) {
                        zeType = zePath.substring(zeTypeNum);
                    }
                    if (zeType.equals(".png")) {
                        ByteArrayOutputStream outImg = new ByteArrayOutputStream();
                        byte[] buffer = new byte[1024];
                        while ((len = zin.read(buffer)) != -1) {
                            outImg.write(buffer, 0, len);
                        }
                        byteArrayOutputStreams.add(outImg);
                    }
                }
            }
            zin.closeEntry();
        } catch (IOException e) {
            e.printStackTrace();
        }
        framenum = config.getInt();//获取config文件中的帧数
        playCount = config.getInt();//获取config文件中的播放次数

        for (int i = 0; i < byteArrayOutputStreams.size(); i++) {
            try {
                delay_time = config.getInt(i * 4 + 8);
            } catch (Exception e) {
                delay_time = 0;
            }
//            当某一帧的停留时间为0时  默认为50
            if (delay_time == 0) delay_time = 50;
//            根据config文件限制获取的帧数
            if (i <= framenum) {
                imageByteConfigs.add(new ImageByteConfig(byteArrayOutputStreams.get(i),
                        delay_time));
            } else {
                break;
            }
        }
        return imageByteConfigs;
    }

    private void setResId(ArrayList<ImageByteConfig> images) {
        this.images = images;
    }

    /**
     * @param imageView
     * @return progress dialog animation
     */
    public FramesSequenceAnimation createProgressDialogAnim(ImageView imageView) {
        return new FramesSequenceAnimation(imageView, images, playCount);
    }


    /**
     * 读取帧---播放帧
     */
    public class FramesSequenceAnimation {
        private int mIndex; // 当前帧数
        private int mDelayMillis;//帧动画时间间隔，毫秒
        public int playCount;//需要循环播放次数
        public int playCountNum = 0;//当前播放次数
        private boolean mShouldRun; // 开始/停止播放用
        private boolean mIsRunning; // 动画是否正在播放，防止重复播放
        private Handler mHandler;
        private Bitmap mBitmap = null;
        private BitmapFactory.Options mBitmapOptions;//Bitmap管理类，可有效减少Bitmap的OOM问题
        private ArrayList<ImageByteConfig> images; // 帧的图片数据数组
        private SoftReference<ImageView> mSoftReferenceImageView; // 软引用ImageView，以便及时释放掉
        private OnAnimationStoppedListener mOnAnimationStoppedListener; //播放停止监听


        public FramesSequenceAnimation(final ImageView imageView, ArrayList<ImageByteConfig>
                images, int playCount) {
            mIndex = -1;
            this.images = images;
            this.playCount = playCount;
            mShouldRun = false;
            mIsRunning = false;
            mDelayMillis = 1000 / images.get(0).getDelay_time();
            mHandler = new Handler() {

                @Override
                public void handleMessage(Message msg) {
                    Bundle bundle = msg.getData();
                    Bitmap bitmap = bundle.getParcelable("bitmap");
                    imageView.setImageBitmap(bitmap);
                }
            };
            mSoftReferenceImageView = new SoftReference<ImageView>(imageView);
            Bitmap bitmap = BitmapFactory.decodeByteArray(images.get(0).getImage().toByteArray(),
                    0, images.get(0).getImage().size());
            if (bitmap != null) imageView.setImageBitmap(bitmap);
            // 当图片大小类型相同时进行复用，避免频繁GC
            if (Build.VERSION.SDK_INT >= 11) {
                Bitmap bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
                int width = bmp.getWidth();
                int height = bmp.getHeight();
                Bitmap.Config config = bmp.getConfig();
                mBitmap = Bitmap.createBitmap(width, height, config);
                mBitmapOptions = new BitmapFactory.Options();
                //设置Bitmap内存复用
                mBitmapOptions.inBitmap = mBitmap;//Bitmap复用内存块，类似对象池，避免不必要的内存分配和回收
                mBitmapOptions.inMutable = true;//解码时返回可变Bitmap
                mBitmapOptions.inSampleSize = 1;//缩放比例
            }
        }

        //循环读取下一帧
        private ByteArrayOutputStream getNext() {
            mIndex++;
            if (mIndex >= images.size()) {
                mIndex = 0;
                playCountNum++;
            }
            //限制播放次数
            if (playCount != 0 && playCountNum == playCount) {
                stop();
            }
            mDelayMillis = 1000 / images.get(mIndex).getDelay_time();
            return images.get(mIndex).getImage();
        }

        /**
         * 播放动画，同步锁防止多线程读帧时，数据安全问题
         */
        public synchronized void start() {
            mShouldRun = true;
            if (mIsRunning) return;
            new Thread(runnable).start();
        }


        final Runnable runnable = new Runnable() {
            @Override
            public void run() {
                Thread t = Thread.currentThread();
                LUtils.e(t.getName());
                ImageView imageView = mSoftReferenceImageView.get();
                if (!mShouldRun || imageView == null) {
                    mIsRunning = false;
                    if (mOnAnimationStoppedListener != null) {
                        mOnAnimationStoppedListener.AnimationStopped();
                    }
                    return;
                }

                mIsRunning = true;
                //新开线程去读下一帧
//                mHandler.postDelayed(this, mDelayMillis);
                Thread thread = new Thread(this);
                try {
                    thread.sleep(mDelayMillis);
                    thread.start();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (imageView.isShown()) {
                    ByteArrayOutputStream image = getNext();
                    if (mBitmap != null) { // so Build.VERSION.SDK_INT >= 11
                        Bitmap bitmap = null;
                        try {
                            bitmap = BitmapFactory.decodeByteArray(image.toByteArray(), 0, image
                                    .size());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        if (bitmap != null) {
                            LUtils.e("显示" + mIndex);
//                                imageView.setImageBitmap(bitmap);
                            Message msg = new Message();
                            Bundle bundle = new Bundle();
                            bundle.putParcelable("bitmap", bitmap);
                            msg.setData(bundle);
                            mHandler.sendMessage(msg);
                        } else {
                            mBitmap.recycle();
                            mBitmap = null;
                        }
                    }
                }

            }


        };


        /**
         * 停止播放
         */
        public synchronized void stop() {
            mShouldRun = false;
        }

        /**
         * 设置停止播放监听
         *
         * @param listener
         */
        public void setOnAnimStopListener(OnAnimationStoppedListener listener) {
            this.mOnAnimationStoppedListener = listener;
        }
    }


    /**
     * 停止播放监听
     */
    public interface OnAnimationStoppedListener {
        void AnimationStopped();
    }

    /***
     * 数据及配置
     */

    public class ImageByteConfig {
        private ByteArrayOutputStream image;//图片字节流
        private int delay_time;//每一帧显示的时间

        public ImageByteConfig(ByteArrayOutputStream image, int delay_time) {
            this.image = image;
            this.delay_time = delay_time;
        }

        public ByteArrayOutputStream getImage() {
            return image;
        }

        public int getDelay_time() {
            return delay_time;
        }
    }
}
